package czh.cocoa.ui.impl;

import android.graphics.Matrix;
import czh.cocoa.animation.CAAnimation;
import czh.cocoa.animation.CAAnimationDelegate;
import czh.cocoa.animation.CABasicAnimation;
import czh.cocoa.animation.CALayer;
import czh.cocoa.animation.CAMediaTimingFunction;
import czh.cocoa.foundation.NSNumber;
import czh.cocoa.foundation.NSObject;
import czh.cocoa.foundation.NSSelector;
import czh.cocoa.foundation.NSSet;
import czh.cocoa.foundation.NSString;
import czh.cocoa.graphics.CGAffineTransform;
import czh.cocoa.graphics.CGContext;
import czh.cocoa.graphics.CGPoint;
import czh.cocoa.graphics.CGRect;
import czh.cocoa.graphics.CGSize;
import czh.cocoa.ui.UIAnimationBlock;
import czh.cocoa.ui.UIEdgeInsets;
import czh.cocoa.ui.UIEvent;
import czh.cocoa.ui.UIGestureRecognizer;
import czh.cocoa.ui.UIImage;
import czh.cocoa.ui.UIView;
import czh.cocoa.ui.gesture.UIPanGestureRecognizer;
import czh.cocoa.ui.gesture.UIPinchGestureRecognizer;

import static czh.cocoa.ui.UIGestureRecognizer.*;
import static czh.cocoa.graphics.CGAffineTransform.*;
import static java.lang.Math.*;

public class UIScrollView extends UIView {  

	private final static float DECELERATION = 1000;
	private final static float VELOCITY = 1000;
	
	private final static NSString SCROLL_ANIM_KEY = NSTR("scroll");
	private final static NSString SCROLL_ANIM2_KEY = NSTR("scroll2");
	private final static NSString INDICATOR_FADEIN_KEY = NSTR("fade_in");
	private final static NSString INDICATOR_FADEOUT_KEY = NSTR("fade_out");
	
	private CGSize mContentSize;
	
	private CGPoint mContentOffset;
	
	private float mDecelerationRate;
	
	private UIImageView mVerticalIndicator;
	
	private UIImageView mHorizontalIndicator;
	
	private boolean mPagingEnabled;
	
	private float mMinimumZoomScale;
	
	private float mMaximumZoomScale;
	
	private float mZoomScale;
	
	private CGSize mOriginScaleSize;
	
	private UIPinchGestureRecognizer mPinchScaler;
	
	private UIScrollViewDelegate mDelegate;
	
	private UIEdgeInsets mContentInset;
	
	private boolean mShowsHorizontalScrollIndicator;
	
	private boolean mShowsVerticalScrollIndicator;
	
	public UIScrollView() {
		
	}
	
	public UIScrollView(CGRect frame) {
		super(frame);
	}
	
	protected void init() {   
		super.init();
		mContentSize = CGSizeMake(0, 0);
		mContentOffset = CGPointMake(0, 0);
		mContentInset = UIEdgeInsetsMake(0, 0, 0, 0);
		setClipsToBounds(true);
		
		mDecelerationRate = 1;
		mMinimumZoomScale = 1;
		mMaximumZoomScale = 1;
		mZoomScale = 1;
		
		mShowsHorizontalScrollIndicator = true;
		mShowsVerticalScrollIndicator = true;
		
		UIImage indicator_img = UIImage.imageNamed(NSTR("cocoa/scroll_indicator.png")); 
		float indicator_width = DIP(indicator_img.size().width);
		float indicator_height = DIP(indicator_img.size().height);
		
		UIImageView v_indicator = new UIImageView(indicator_img);
		v_indicator.setFrame(CGRectMake(
				frame().size.width - indicator_width, 0, indicator_width, indicator_height));
		v_indicator.setContentStretch(CGRectMake(0, 0.428f, 1, 0.144f)); 
		v_indicator.setAutoresizingMask(UIViewAutoresizingFlexibleLeftMargin | 
				UIViewAutoresizingFlexibleBottomMargin);
		v_indicator.setAlpha(0);
		//v_indicator.setHidden(true);
		addSubview(v_indicator); 
		
		mVerticalIndicator = v_indicator;
		
		UIImageView h_indicator = new UIImageView(indicator_img);
		h_indicator.setFrame(CGRectMake(
				0, frame().size.height - indicator_height, indicator_width, indicator_height));
		h_indicator.setContentStretch(CGRectMake(0.428f, 0, 0.144f, 1)); 
		h_indicator.setAutoresizingMask(UIViewAutoresizingFlexibleRightMargin | 
				UIViewAutoresizingFlexibleTopMargin);
		h_indicator.setAlpha(0);
		//h_indicator.setHidden(true);
		addSubview(h_indicator); 
		
		mHorizontalIndicator = h_indicator;
		
		UIGestureRecognizer delay = new DelayedTouchesBeganGestureRecognizer();
		delay.setDelaysTouchesBegan(true);
		addGestureRecognizer(delay);
		
		final UIPanGestureRecognizer pan = new UIPanGestureRecognizer();
		
		//pan.setDelaysTouchesBegan(true);
		
		pan.addTargetAction(this, new NSSelector() {
			@Override
			public void perform(NSObject receiver, NSObject params) {
				handlePanGesture(pan);
			}
		});
		addGestureRecognizer(pan);
	}
	
	public void setDelegate(UIScrollViewDelegate delegate) {
		mDelegate = delegate;
	}
	
	public UIScrollViewDelegate delegate() {
		return mDelegate;
	}
	
	private void handlePanGesture(UIPanGestureRecognizer pan) {
		int state = pan.state();
		switch (state) {
		case UIGestureRecognizerStateBegan:
		case UIGestureRecognizerStateChanged:
		case UIGestureRecognizerStateEnded:
		{
			CGRect bounds = bounds();
			
			if (state == UIGestureRecognizerStateBegan) { 
				layer().removeAnimationForKey(SCROLL_ANIM_KEY);
				mVerticalIndicator.layer().removeAnimationForKey(SCROLL_ANIM_KEY); 
				mHorizontalIndicator.layer().removeAnimationForKey(SCROLL_ANIM_KEY); 
				
				if (isVerticalScrollIndicatorAvailable(bounds)) {
					setScrollIndicatorVisibleAnimated(mVerticalIndicator, true);
				}
				if (isHorizontalScrollIndicatorAvailable(bounds)) {
					setScrollIndicatorVisibleAnimated(mHorizontalIndicator, true);
				}
				
				mContentOffset = contentOffset();
			}
			
			CGPoint translation = pan.translationInView(this); 
			final float offx = mContentOffset.x - translation.x;
			final float offy = mContentOffset.y - translation.y;
			
//			float offx_max = Math.max(0, mContentSize.width - bounds.size.width);
//			if (offx > 0) {
//				offx = Math.min(offx, offx_max);
//			} else {
//				offx = 0;
//			}
//			
//			float offy_max = Math.max(0, mContentSize.height - bounds.size.height);
//			if (offy > 0) { 
//				offy = Math.min(offy, offy_max);
//			} else {
//				offy = 0;
//			}
			
			final CGPoint content_offset = CGPointMake(offx, offy);
			
			adjustScrollContentOffset(content_offset, bounds); 
			
			setContentOffset(content_offset); 
			
			bounds = bounds();
			
			if (isVerticalScrollIndicatorAvailable(bounds)) {
				adjustVerticalScrollIndicator(bounds); 
			}
			
			if (isHorizontalScrollIndicatorAvailable(bounds)) {
				adjustHorizontalScrollIndicator(bounds); 
			}
			
			if (state == UIGestureRecognizerStateEnded) {
				if (mPagingEnabled) {

					int sx = round(bounds.origin.x / bounds.size.width);
					int sy = round(bounds.origin.y / bounds.size.height);
					CGPoint offset = CGPointMake(bounds.size.width * sx, bounds.size.height * sy);
					
					decelerateToStopScrolling(offset, 5000);
					
				} else {
					
					CGPoint velocity = pan.velocityInView(this);
					
					float deceleration = DECELERATION * mDecelerationRate;
					
					
					
					if (velocity.x != 0) {
						float vx = Math.abs(velocity.x);
						if (vx != 0) { 
							content_offset.x += vx * vx / (deceleration * 2) * (-vx / velocity.x);
						}
						
//						if (offx > 0) {
//							offx = Math.min(offx, offx_max);
//						} else {
//							offx = 0;
//						}
					}
					
					if (velocity.y != 0) {
						float vy = Math.abs(velocity.y);
						if (vy != 0) { 
							content_offset.y += vy * vy / (deceleration * 2) * (-vy / velocity.y);
						}
						
//						if (offy > 0) { 
//							offy = Math.min(offy, offy_max);
//						} else {
//							offy = 0;
//						}
					}
					
					adjustScrollContentOffset(content_offset, bounds);
					
					decelerateToStopScrolling(content_offset, deceleration); 
				}
			}
			
		}
			break;
		default:
			break;
		}
	}
	
//	private void scrollToMultipleBounds() {
//		CGRect bounds = bounds();
//		int sx = round(bounds.origin.x / bounds.size.width);
//		int sy = round(bounds.origin.y / bounds.size.height);
//		CGPoint offset = CGPointMake(bounds.size.width * sx, bounds.size.height * sy); 
//		setContentOffsetAnimated(offset, true);
//	}
	
	private void decelerateToStopScrolling(final CGPoint contentOffset, float deceleration) {
		
		double duration = 0;
		
		//final CGPoint contentOffset0 = contentOffset();
		
		double begin_time = System.currentTimeMillis() / 1000.0;
		
		final CGRect bounds = bounds();
		
		final CGPoint contentOffset0 = bounds.origin;
		
		final boolean v_indicator_enabled = isVerticalScrollIndicatorAvailable(bounds);
		final boolean h_indicator_enabled = isHorizontalScrollIndicatorAvailable(bounds);
		
		if (!contentOffset0.isEqual(contentOffset)) { 
			
			if (mDelegate != null) {
				mDelegate.scrollViewDidEndDraggingWillDecelerate(this, true);
				mDelegate.scrollViewWillBeginDecelerating(this);
			}
			
			//setContentOffset(contentOffset); 
			//bounds.origin = contentOffset;
			
			float duration_x = (float) sqrt(abs((contentOffset.x - contentOffset0.x) * 2 / deceleration));
			float duration_y = (float) sqrt(abs((contentOffset.x - contentOffset0.y) * 2 / deceleration));
			duration = Math.max(duration_x, duration_y);
			
			CABasicAnimation anim = new CABasicAnimation(CALayer.ANIM_BOUNDS);
			anim.setFromValue(bounds);
			
			CGRect bounds2 = new CGRect(bounds);
			bounds2.origin = contentOffset;
			anim.setToValue(bounds2);
			
			anim.setDuration(duration);
			anim.setTimingFunction(CAMediaTimingFunction.EaseOut); 
			anim.setBeginTime(begin_time);
			
			anim.setDelegate(new CAAnimationDelegate() {
				@Override
				public void animationDidStop(CAAnimation anim, boolean finished) {
					//if (!finished) {
//						float progress = anim.progress();
//						float offx = contentOffset0.x + (contentOffset.x - contentOffset0.x) * progress;
//						float offy = contentOffset0.y + (contentOffset.y - contentOffset0.y) * progress;
//						setContentOffset(CGPointMake(offx, offy));  
					//}
					
					if (v_indicator_enabled) {
						setScrollIndicatorVisibleAnimated(mVerticalIndicator, false);
					}
					
					if (h_indicator_enabled) { 
						setScrollIndicatorVisibleAnimated(mHorizontalIndicator, false);
					}
					
					if (mDelegate != null) {
						mDelegate.scrollViewDidEndDecelerating(UIScrollView.this);
					}
				}
				@Override
				public void animationOnProcessing(CAAnimation anim) {
					float progress = anim.progress();
					float offx = contentOffset0.x + (contentOffset.x - contentOffset0.x) * progress;
					float offy = contentOffset0.y + (contentOffset.y - contentOffset0.y) * progress;
					setContentOffset(CGPointMake(offx, offy)); 
					
					CGRect bounds = bounds();
					
					if (v_indicator_enabled) {
						adjustVerticalScrollIndicator(bounds);
					}
					
					if (h_indicator_enabled) { 
						adjustHorizontalScrollIndicator(bounds);
					}
					
				}
				@Override
				public void animationDidStart(CAAnimation anim) {}
			});
			
			layer().addAnimationForKey(anim, SCROLL_ANIM_KEY);
			
			//NSLog("decelerate to stop scrolling !");
			
//			if (isVerticalScrollIndicatorAvailable(bounds)) { 
//				
//				final CGRect indicator_frame = mVerticalIndicator.frame();
//				
//				adjustVerticalScrollIndicator(bounds);
//				
//				final CGRect indicator_frame2 = mVerticalIndicator.frame();
//				
//				CABasicAnimation anim2 = new CABasicAnimation(CALayer.ANIM_FRAME);
//				anim2.setFromValue(indicator_frame);
//				anim2.setDuration(duration);
//				anim2.setTimingFunction(CAMediaTimingFunction.EaseOut); 
//				anim2.setBeginTime(begin_time);
//				anim2.setDelegate(new CAAnimationDelegate() {
//					@Override
//					public void animationDidStop(CAAnimation anim, boolean finished) {
//						setScrollIndicatorVisibleAnimated(mVerticalIndicator, false);
//						if (!finished) {
//							float progress = anim.progress();
//							CGRect frame = indicator_frame;
//							frame.origin.y += (indicator_frame2.origin.y - indicator_frame.origin.y) * progress;
//							mVerticalIndicator.setFrame(frame); 
//						}
//					}
//					@Override
//					public void animationDidStart(CAAnimation anim) {}
//					@Override
//					public void animationOnProcessing(CAAnimation anim) {}
//				});
//				mVerticalIndicator.layer().addAnimationForKey(anim2, SCROLL_ANIM_KEY);
//				
//			} 
			
//			if (isHorizontalScrollIndicatorAvailable(bounds)) { 
//				
//				final CGRect indicator_frame = mHorizontalIndicator.frame();
//				
//				adjustHorizontalScrollIndicator(bounds);
//				
//				final CGRect indicator_frame2 = mHorizontalIndicator.frame();
//				
//				CABasicAnimation anim2 = new CABasicAnimation(CALayer.ANIM_FRAME);
//				anim2.setFromValue(indicator_frame);
//				anim2.setDuration(duration);
//				anim2.setTimingFunction(CAMediaTimingFunction.EaseOut); 
//				anim2.setBeginTime(begin_time);
//				anim2.setDelegate(new CAAnimationDelegate() {
//					@Override
//					public void animationDidStop(CAAnimation anim, boolean finished) {
//						setScrollIndicatorVisibleAnimated(mHorizontalIndicator, false);
//						if (!finished) {
//							float progress = anim.progress();
//							CGRect frame = indicator_frame;
//							frame.origin.x += (indicator_frame2.origin.x - indicator_frame.origin.x) * progress;
//							mHorizontalIndicator.setFrame(frame); 
//						}
//					}
//					@Override
//					public void animationDidStart(CAAnimation anim) {}
//					@Override
//					public void animationOnProcessing(CAAnimation anim) {}
//				});
//				mHorizontalIndicator.layer().addAnimationForKey(anim2, SCROLL_ANIM_KEY);
//				
//			} 
			
		} else {
			
			if (v_indicator_enabled) { 
				setScrollIndicatorVisibleAnimated(mVerticalIndicator, false);
			}
			
			if (h_indicator_enabled) {
				setScrollIndicatorVisibleAnimated(mHorizontalIndicator, false);
			}
			
			if (mDelegate != null) {
				mDelegate.scrollViewDidEndDraggingWillDecelerate(this, false);
			}
			
		}
		
	
	}
	
	public void setContentSize(CGSize size) {
		mContentSize = new CGSize(size);
	}
	
	public CGSize contentSize() {
		return new CGSize(mContentSize);
	}
	
	public void setContentOffset(CGPoint offset) {
		
		CGRect bounds = bounds();
		
		if (!bounds.origin.isEqual(offset)) {
			bounds.origin.x = offset.x;
			bounds.origin.y = offset.y;
			setBounds(bounds);
			
			scrollViewDidScroll();
		}

	}
	
	protected void scrollViewDidScroll() {
		if (mDelegate != null) {
			mDelegate.scrollViewDidScroll(this);
		}
	}
	
	public void setContentOffsetAnimated(CGPoint offset, boolean animated) {
		if (!animated) {
			setContentOffset(offset);
		} else {
			CGPoint offset0 = contentOffset();
			float dist_x = offset.x - offset0.x;
			float dist_y = offset.y - offset0.y;
			double duration = max(abs(dist_x)/VELOCITY, abs(dist_y)/VELOCITY);
			
			CGRect bounds = bounds();
			
			setContentOffset(offset);
			
			CABasicAnimation anim = new CABasicAnimation(CALayer.ANIM_BOUNDS);
			anim.setFromValue(bounds);
			anim.setDuration(duration);
			anim.setTimingFunction(CAMediaTimingFunction.EaseOut);
			layer().addAnimationForKey(anim, SCROLL_ANIM2_KEY);

		}
	}
	
	public CGPoint contentOffset() {
		return bounds().origin;
	}
	
	public void setDecelerationRate(float rate) {
		mDecelerationRate = rate;
	}
	
	public float decelerationRate() {
		return mDecelerationRate;
	}
	
	//  offy = (offy0 + (offy2 - offy0) * progress) * k
	
	private void adjustVerticalScrollIndicator(CGRect bounds) {
		
		CGRect v_indicator_frame = mVerticalIndicator.frame();
		
		float total_height = mContentSize.height + mContentInset.top + mContentInset.bottom;
		
		v_indicator_frame.size.height = bounds.size.height * bounds.size.height / total_height;
		v_indicator_frame.origin.y = (bounds.origin.y + mContentInset.top)
		                   * bounds.size.height / total_height + bounds.origin.y; 
		v_indicator_frame.origin.x = bounds.size.width - v_indicator_frame.size.width + bounds.origin.x;
		
		mVerticalIndicator.setFrame(v_indicator_frame);
			
	    // -100 ~ -90
		// 0 - inset_top   <= offy <= mContentSize.height - bounds.size.height + inset_bottom
	}
	
	private void adjustHorizontalScrollIndicator(CGRect bounds) {
		
		CGRect h_indicator_frame = mHorizontalIndicator.frame();
		
		float total_width = mContentSize.width + mContentInset.left + mContentInset.right;
		
		h_indicator_frame.size.width = bounds.size.width * bounds.size.width / total_width;
		h_indicator_frame.origin.x = (bounds.origin.x + mContentInset.left) 
						   * bounds.size.width / total_width + bounds.origin.x; 
		h_indicator_frame.origin.y = bounds.size.height - h_indicator_frame.size.height + bounds.origin.y;
		
		mHorizontalIndicator.setFrame(h_indicator_frame);
		
	}
	
	private boolean isVerticalScrollIndicatorAvailable(CGRect bounds) {
		return mShowsVerticalScrollIndicator &&
		       bounds.size.height < mContentSize.height + mContentInset.top + mContentInset.bottom;
	}
	
	private boolean isHorizontalScrollIndicatorAvailable(CGRect bounds) {
		return mShowsHorizontalScrollIndicator &&
		       bounds.size.width < mContentSize.width + mContentInset.left + mContentInset.right;
	}
	
	private void setScrollIndicatorVisibleAnimated(final UIView indicator, boolean visible) {		
		 
		if (visible) {
	
			if (indicator.layer().animationForKey(INDICATOR_FADEIN_KEY) == null) { 
				
				//NSLog("scroll indicator visible: %b", visible);
				
				bringSubviewToFront(indicator);
				
				indicator.layer().removeAnimationForKey(INDICATOR_FADEOUT_KEY);
				
				CABasicAnimation anim = new CABasicAnimation(CALayer.ANIM_OPACITY);
				anim.setToValue(new NSNumber(1));
				anim.setDelegate(new CAAnimationDelegate() {
					@Override
					public void animationDidStop(CAAnimation anim, boolean finished) {
						float progress = anim.progress();
						float alpha = indicator.alpha();
						indicator.setAlpha(alpha + (1 - alpha) * progress);
						
						//NSLog("indicator fade in !");
					}
					@Override
					public void animationDidStart(CAAnimation anim) {}
					@Override
					public void animationOnProcessing(CAAnimation anim) {}
				});
				indicator.layer().addAnimationForKey(anim, INDICATOR_FADEIN_KEY); 

			}
			
		} else {
			
			if (indicator.layer().animationForKey(INDICATOR_FADEOUT_KEY) == null) { 
				
				//NSLog("scroll indicator visible: %b", visible);
				
				indicator.layer().removeAnimationForKey(INDICATOR_FADEIN_KEY);
				
				CABasicAnimation anim = new CABasicAnimation(CALayer.ANIM_OPACITY);
				anim.setToValue(new NSNumber(0));
				anim.setDelegate(new CAAnimationDelegate() {
					@Override
					public void animationDidStop(CAAnimation anim, boolean finished) {
						float progress = anim.progress();
						float alpha = indicator.alpha();
						indicator.setAlpha(alpha + (0 - alpha) * progress);
						
						//NSLog("indicator fade out !");
					}
					@Override
					public void animationDidStart(CAAnimation anim) {}
					@Override
					public void animationOnProcessing(CAAnimation anim) {}
				});
				indicator.layer().addAnimationForKey(anim, INDICATOR_FADEOUT_KEY); 

			}
			
		}
	}
	
	public void setPagingEnabled(boolean enabled) {
		mPagingEnabled = enabled;
	}
	
	public boolean isPagingEnabled() {
		return mPagingEnabled;
	}
	
	public void setMinimumZoomScale(float scale) {
		mMinimumZoomScale = scale;
		updatePinchScaleRecognizer();
	}
	
	public float minimumZoomScale() {
		return mMinimumZoomScale;
	}
	
	public void setMaximumZoomScale(float scale) {
		mMaximumZoomScale = scale;
		updatePinchScaleRecognizer();
	}
	
	public float maximumZoomScale() {
		return mMaximumZoomScale;
	}
	
	public void setZoomScale(float scale) {
		mZoomScale = scale;
	}
	
	public float zoomScale() {
		return mZoomScale;
	}
	
	private void updatePinchScaleRecognizer() {
		if (mMinimumZoomScale != 1 || mMaximumZoomScale != 1) {
			if (mPinchScaler == null) {
				mPinchScaler = new UIPinchGestureRecognizer();
				mPinchScaler.addTargetAction(this, new NSSelector() {
					@Override
					public void perform(NSObject receiver, NSObject params) {
						handlePinchGesture(mPinchScaler);
					}
				});
				addGestureRecognizer(mPinchScaler);
			}
		} else {
			if (mPinchScaler != null) {
				removeGestureRecognizer(mPinchScaler);
				mPinchScaler = null;
			}
		}
	}
	
	private void handlePinchGesture(UIPinchGestureRecognizer pinch) {
		int state = pinch.state();
		switch (state) { 
		case UIGestureRecognizerStateBegan:
		case UIGestureRecognizerStateChanged:
		case UIGestureRecognizerStateEnded:
			if (mDelegate != null) {
				UIView view = mDelegate.viewForZoomingInScrollView(this);
				if (view != null) {
					CGRect frame = view.frame();
					
					if (state == UIGestureRecognizerStateBegan) {
						mOriginScaleSize = new CGSize(frame.size);
					}
					 
					float scale = pinch.scale();
					
					if (scale <= 0) {
						scale = 0.01f;
					}
					
					//NSLog("scroll view scale: " + scale);
					
					float total_scale = min(mMaximumZoomScale, mZoomScale * scale);
					total_scale = max(mMinimumZoomScale, total_scale);
					
					scale = total_scale / mZoomScale;
					
					//scale = total_scale / mZoomScale;
					
					setContentSize(CGSizeMake(mOriginScaleSize.width * scale, 
							mOriginScaleSize.height * scale)); 
					
					if (state == UIGestureRecognizerStateEnded) {
						mZoomScale *= scale;
						NSLog("zoom scale: " + mZoomScale);
					}
						
						CGRect bounds = bounds();
						
						float offx = bounds.origin.x + (mContentSize.width - frame.size.width) / 2;
						float offy = bounds.origin.y + (mContentSize.height - frame.size.height) / 2;
						
//						float offx_max = Math.max(0, mContentSize.width - bounds.size.width);
//						if (offx > 0) {
//							offx = Math.min(offx, offx_max);
//						} else {
//							offx = 0;
//						}
//						
//						float offy_max = Math.max(0, mContentSize.height - bounds.size.height);
//						if (offy > 0) { 
//							offy = Math.min(offy, offy_max);
//						} else {
//							offy = 0;
//						}
						
						CGPoint offset = CGPointMake(offx, offy);
						adjustScrollContentOffset(offset, bounds);
						
						setContentOffsetAnimated(offset, false); 
						
						frame.size = new CGSize(mContentSize);
						view.setFrame(frame);
						//view.setTransform(new CGAffineTransform());
						
						
//					} else {
//						
//						CGAffineTransform transform = new CGAffineTransform();
//						transform.scale(scale, scale); 
//						
//						view.setTransform(transform); 
//						
//					}
				}
			}
			break;
		default:
			break;
		}
	}
	
	public void setContentInset(UIEdgeInsets insets) {
		mContentInset = new UIEdgeInsets(insets);
	}
	
	public UIEdgeInsets contentInset() {
		return new UIEdgeInsets(mContentInset);
	}
	
	private void adjustScrollContentOffset(CGPoint offset, CGRect bounds) {
		float offx_min = -mContentInset.left;
		float offx_max = mContentSize.width - bounds.size.width + mContentInset.right;
		if (offset.x > offx_min && offx_max > offx_min) {
			offset.x = min(offset.x, offx_max);
		} else {
			offset.x = offx_min;
		}
		
		float offy_min = -mContentInset.top;
		float offy_max = mContentSize.height - bounds.size.height + mContentInset.bottom;
		if (offset.y > offy_min && offy_max > offy_min) {
			offset.y = min(offset.y, offy_max);
		} else {
			offset.y = offy_min;
		}
		
		//  0 - inset_top   <= offy <= mContentSize.height - bounds.size.height + inset_bottom
	}
	
	public void setShowsHorizontalScrollIndicator(boolean shown) {
		mShowsHorizontalScrollIndicator = shown;
	}
	
	public boolean showsHorizontalScrollIndicator() {
		return mShowsHorizontalScrollIndicator;
	}
	
	public void setShowsVerticalScrollIndicator(boolean shown) {
		mShowsVerticalScrollIndicator = shown;
	}
	
	public boolean showsVerticalScrollIndicator() {
		return mShowsVerticalScrollIndicator;
	}
	
	private class DelayedTouchesBeganGestureRecognizer extends UIGestureRecognizer {
		
		public void touchesBeganWithEvent(NSSet touches, UIEvent event) {
			setState(UIGestureRecognizerStatePossible);
			performSelectorWithObjectAfterDelay(NSTR("failed"), null, 0.2); 
		}
		
		public void touchesMovedWithEvent(NSSet touches, UIEvent event) {
			
		}
		
		public void touchesEndedWithEvent(NSSet touches, UIEvent event) {
			setState(UIGestureRecognizerStateFailed);
		}
		
		public void touchesCancelledWithEvent(NSSet touches, UIEvent event) {
			setState(UIGestureRecognizerStateFailed);
		}
		
		@SuppressWarnings("unused")
		private void failed() {
			setState(UIGestureRecognizerStateFailed); 
		}
		
	}
	
}
